package com.youtills.core.lang;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: ravi
 * Date: 9/5/12
 * Time: 11:34 AM
 * To change this template use File | Settings | File Templates.
 */
public class InstanceMaker<T> {

    /** Cached instances. */
    private Map<String, T> instances = null;

    private boolean useCache;
    /**
     * Creates a new InstanceMaker object.
     */
    public InstanceMaker() {
        this(false);
    }

    /**
     * Creates a new InstanceMaker object.
     *
     * @param  useCache true to cache instances.
     */
    public InstanceMaker(final boolean useCache) {
        this.useCache = useCache;
        if (useCache) {
            instances = new HashMap<String, T>();
        }
    }


    public static <T> T newInstanceOf(Class<T> clazz) {
        return (T) newInstanceOf(clazz.getName());
    }

    public static Object newInstanceOf(String className) {
        try {
            Class clazz = Class.forName(className);
            //noinspection unchecked
            return clazz.newInstance();
        } catch (ClassNotFoundException e) {
            throw new YoutillsRuntimeException(e, className, " is not Found.");
        } catch (IllegalAccessException e) {
            throw new YoutillsRuntimeException(e, className, " is not accessible.");
        } catch (InstantiationException e) {
            throw new YoutillsRuntimeException(e, "Unable to create an instance for ", className);
        }
    }

    /**
     * Creates an instance of type T for given class name..
     *
     * @param   className  class name to create instance.
     *
     * @return  instance of type T
     */
    public T getInstanceOf(final String className) {

        T val;

        if (useCache) {

            if ( instances.get(className) != null) {
                return instances.get(className);
            }
        }

        //noinspection unchecked
        val = (T) newInstanceOf(className);

        if (useCache) {
            instances.put(className, val);
        }

        return val;
    }

}
